// import { getToken } from '@/store/token'
// import statusCodeInterceptor from './statusCodeInterceptor'
import { showToast } from './toast'
// import { R } from './type/response'

const domain = 'http://localhost:3001'

/**
 * 接口地址前缀
 */
export const BASE_URL = domain
/**
 * 资源文件源地址前缀
 */
export const RESOURCES_URL = domain
type MethodType =
  | 'OPTIONS'
  | 'GET'
  | 'HEAD'
  | 'POST'
  | 'PUT'
  | 'DELETE'
  | 'TRACE'
  | 'CONNECT'
/**
 *
 * @param {string} method
 * @param {string} url
 * @param {object} data
 * @returns {Promise}
 */
const send = async <T = any>(
  method: MethodType,
  url: string,
  data: object | FormData | null = null,
  other: any = {}
): Promise<R<T>> => {
  const header: any = {}
  let body: FormData | string | null = null
  if (data != null) {
    if (data instanceof FormData) {
      body = data
    } else {
      header['Content-Type'] = 'application/json;charset=UTF-8'
      body = JSON.stringify(data)
    }
  }
  if (method.toUpperCase() == 'GET' || method.toUpperCase() == 'HEAD') {
    body = null
  }
  if (typeof other['header'] == 'object') {
    for (let item in other['header']) {
      header[item] = other['header'][item]
    }
    other['header'] = undefined
  }
  let resultData = null
  try {
    const realUrl =
      url.indexOf('http://') == 0 || url.indexOf('https://') == 0
        ? url
        : BASE_URL + url
    const result = await fetch(realUrl, {
      method,
      headers: header,
      body,
    })
    // console.log(body)

    resultData = await result.json()
  } catch (e: any) {
    if (e.errMsg && e.errMsg.includes('fail timeout')) {
      showToast('网络异常')
      throw '网络异常'
    }
    console.log(e)
  }
  if (resultData == null) {
    showToast('网络异常')
    return new R<T>({
      code: 500,
      msg: '网络异常',
    })
  }

  const _data = resultData as any as R<T>
  return new R<T>(_data)
}

const getQueryUrl = (url: string, data: any = null): string => {
  let init = false
  for (let item in data) {
    if (
      typeof data[item] == 'boolean' ||
      typeof data[item] == 'number' ||
      typeof data[item] == 'string'
    ) {
      const prefix = init ? '&' : '?'
      init = true
      url += `${prefix}${item}=${data[item]}`
    } else if (typeof data[item] == 'object') {
      throw new Error('get或del请求不能出现object类型的参数')
    }
  }
  return url
}

/**
 * @returns
 */
const get = <T = any>(url: string, data: any = null, other: object = {}) => {
  if (data == null) {
    return send<T>('GET', url)
  }
  url = getQueryUrl(url, data)
  return send<T>('GET', url, other)
}
const del = <T>(url: string, data: any = null, other: object = {}) => {
  if (data == null) {
    return send<T>('DELETE', url)
  }
  url = getQueryUrl(url, data)
  return send<T>('DELETE', url, other)
}
/**
 *
 * @param {string} url
 * @param {object} data
 * @returns
 */
const post = <T>(url: string, data: any = {}, other: object = {}) =>
  send<T>('POST', url, data, other)
const put = <T>(url: string, data: any = {}, other: object = {}) =>
  send<T>('PUT', url, data, other)

function fileUpload<T>(url: string, formdata: FormData): Promise<R<T>>
function fileUpload<T>(url: string, filename: string, file: File): Promise<R<T>>

/**
 * 文件上传
 * @param url
 * @param filePath
 * @returns
 */
async function fileUpload<T>(
  url: string,
  formdata: FormData | string,
  file?: File
): Promise<R<T>> {
  if (formdata instanceof FormData) {
    return send<T>('POST', url, formdata)
  }
  const form = new FormData()
  if (!file) {
    throw new Error('file不能为空')
  }
  form.append(formdata, file!, file!.name)
  return send<T>('POST', url, form)
}

const request = {
  get,
  post,
  fileUpload,
  put,
  del,
}

export class R<T> {
  /**
   * 状态码
   */
  code: number
  /**
   * 数据
   */
  data: T
  /**
   * 消息，code为200一般都是 'ok'
   */
  msg: string

  originallyData: any

  constructor(data: any) {
    this.originallyData = data
    this.code = data.code
    this.data = data.data
    this.msg = data.msg
  }
  /**
   * 打开包装，如果code不为1，则弹出错误信息，并且抛出异常堵塞后续代码运行
   * @returns
   */
  unwrap() {
    const msg = this.msg || this.originallyData
    let showMsg = msg
    if (showMsg.length > 60) {
      showMsg = showMsg.substring(0, 60) + '...'
    }
    if (this.code !== 200) {
      showToast(showMsg)
      throw new Error(msg)
    }
    return this.data
  }
  expection(msg: string) {
    if (this.code !== 200) {
      showToast(msg)
      throw new Error(this.msg)
    }
    return this.data
  }
}

export default request
